package com.huffman.smart_picture.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huffman.smart_picture.auth.SpaceUserAuthManager;
import com.huffman.smart_picture.auth.model.SpaceUserRole;
import com.huffman.smart_picture.common.UserSession;
import com.huffman.smart_picture.common.auth.AuthConstant;
import com.huffman.smart_picture.common.exception.BusinessException;
import com.huffman.smart_picture.common.exception.ErrorEnum;
import com.huffman.smart_picture.domain.entity.Space;
import com.huffman.smart_picture.domain.entity.SpaceUser;
import com.huffman.smart_picture.domain.entity.User;
import com.huffman.smart_picture.domain.enums.SpaceLevelEnum;
import com.huffman.smart_picture.domain.enums.SpaceUserEnum;
import com.huffman.smart_picture.domain.request.space.SpaceCreateRequest;
import com.huffman.smart_picture.domain.request.space.SpaceInviteUserRequest;
import com.huffman.smart_picture.domain.vo.manage.DashboardSpaceRatioVo;
import com.huffman.smart_picture.domain.vo.space.AbbreviationSpaceVo;
import com.huffman.smart_picture.domain.vo.space.SpaceUserVo;
import com.huffman.smart_picture.domain.vo.space.SpaceVo;
import com.huffman.smart_picture.mapper.SpaceMapper;
import com.huffman.smart_picture.mapper.UserMapper;
import com.huffman.smart_picture.service.SpaceService;
import com.huffman.smart_picture.service.SpaceUserService;
import com.huffman.smart_picture.utils.ThrowUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author DengLin
 * @description 针对表【space(空间)】的数据库操作Service实现
 * @createDate 2025-02-06 20:21:39
 */
@Service
public class SpaceServiceImpl extends ServiceImpl<SpaceMapper, Space> implements SpaceService {
    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private UserMapper userMapper;

    @Resource
    private SpaceUserService spaceUserService;

    @Resource
    private SpaceUserAuthManager spaceUserAuthManager;

    @Override
    public Long createSpace(SpaceCreateRequest spaceCreateRequest, HttpServletRequest httpServletRequest) {
        // 校验参数
        Space space = SpaceCreateRequest.convert(spaceCreateRequest);

        if (!StringUtils.hasText(space.getSpaceName())) {
            space.setSpaceName("默认空间");
        }

        if (space.getSpaceLevel() == null) {
            space.setSpaceLevel(SpaceLevelEnum.COMMON.getValue());
        }
        // 数据填充
        fillSpaceBySpaceLevel(space);
        // 空间数据校验
        validSpace(space, true);
        UserSession userSession = (UserSession) httpServletRequest.getSession().getAttribute(AuthConstant.LOGIN_USER);

        Long userId = userSession.getId();
        space.setUserId(userId);
        space.setEditTime(new Date());
        space.setTotalCount(0L);
        space.setTotalSize(0L);
        Long spaceId;
        synchronized (userId.toString().intern()) {
            spaceId = transactionTemplate.execute(status -> {
                SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getEnumByValue(space.getSpaceLevel());
                ThrowUtil.throwIf(spaceLevelEnum == null, ErrorEnum.PARAM_EMPTY, "创建失败,参数错误");
                boolean checked = checkUserSpaceAuth(userId, spaceLevelEnum);
                ThrowUtil.throwIf(!checked, ErrorEnum.NO_AUTH, "额度不足");
                boolean saveSuccess = save(space);
                ThrowUtil.throwIf(!saveSuccess, ErrorEnum.SYSTEM_ERROR, "创建失败,系统错误");
                String spaceCountField = spaceLevelEnum.getCountField();
                String spaceLimitField = spaceLevelEnum.getLimitField();
                Integer res = userMapper.updateUserSpaceData(userId, spaceCountField, spaceLimitField);
                ThrowUtil.throwIf(res != 1, ErrorEnum.SYSTEM_ERROR, "创建失败,系统错误");
                // 插入到空间角色表
                SpaceUser spaceUser = new SpaceUser();
                spaceUser.setSpaceRole(SpaceUserEnum.CREATOR.getValue());
                spaceUser.setUserId(userId);
                spaceUser.setSpaceId(space.getId());
                boolean save = spaceUserService.save(spaceUser);
                ThrowUtil.throwIf(!save, ErrorEnum.SYSTEM_ERROR, "创建失败,系统错误");
                return space.getId();
            });
        }
        if (spaceId != null) {
            userSession.getSpaceUserRoleMap().put(spaceId, SpaceUserEnum.CREATOR.getValue());
            httpServletRequest.setAttribute(AuthConstant.LOGIN_USER, userSession);
        }
        return Optional.ofNullable(spaceId).orElse(-1L);
    }

    @Override
    public void validSpace(Space space, boolean create) {
        ThrowUtil.throwIf(space == null, ErrorEnum.PARAM_EMPTY, "请求参数为空");
        String spaceName = space.getSpaceName();
        Integer spaceLevel = space.getSpaceLevel();
        SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getEnumByValue(spaceLevel);
        // 创建条件下
        if (create) {
            // 校验空间名称是否为空
            ThrowUtil.throwIf(!StringUtils.hasText(spaceName), ErrorEnum.PARAM_EMPTY, "空间名称为空");
            // 校验空间级别是否为空
            ThrowUtil.throwIf(spaceLevel == null, ErrorEnum.PARAM_EMPTY, "空间大小为空");
        }
        // 修改空间信息
        // 修改空间级别 空间大小存在 级别不存在
        ThrowUtil.throwIf(spaceLevel != null && spaceLevelEnum == null, ErrorEnum.PARAM_ILLICIT, "空间级别不存在");
        // 修改空间名称 名称过长
        ThrowUtil.throwIf(StringUtils.hasText(spaceName) && spaceName.length() > 30, ErrorEnum.PARAM_ILLICIT, "空间名称过长");
    }

    @Override
    public void fillSpaceBySpaceLevel(Space space) {
        Long spaceMaxSize = space.getMaxSize();
        Long spaceMaxCount = space.getMaxCount();
        Integer spaceLevel = space.getSpaceLevel();
        SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getEnumByValue(spaceLevel);
        if (spaceLevelEnum != null) {
            long maxSize = spaceLevelEnum.getMaxSize();
            if (spaceMaxSize == null) {
                space.setMaxSize(maxSize);
            }
            long maxCount = spaceLevelEnum.getMaxCount();
            if (spaceMaxCount == null) {
                space.setMaxCount(maxCount);
            }
        }
    }

    @Override
    public List<AbbreviationSpaceVo> getAbbreviationSpaceVo(Long userId) {
        List<AbbreviationSpaceVo> abbreviationSpaceVos = lambdaQuery()
                .eq(Space::getUserId, userId)
                .orderBy(true, false, Space::getSpaceLevel)
                .list()
                .stream()
                .map(AbbreviationSpaceVo::convert)
                .collect(Collectors.toList());
        for (AbbreviationSpaceVo abbreviationSpaceVo : abbreviationSpaceVos) {
            List<String> spaceUserAvatar = spaceUserService.getSpaceUserAvatar(abbreviationSpaceVo.getId(), 5);
            abbreviationSpaceVo.setMemberAvatars(spaceUserAvatar);
        }

        return abbreviationSpaceVos;
    }

    @Override
    public boolean inviteUser(SpaceInviteUserRequest spaceInviteUserRequest, UserSession userSession) {
        Long spaceId = spaceInviteUserRequest.getId();
        String username = spaceInviteUserRequest.getUsername();
        Integer spaceUserRole = spaceInviteUserRequest.getSpaceUserRole();
        SpaceUserEnum spaceUserEnum = SpaceUserEnum.getSpaceUserEnum(spaceUserRole);
        // 一个空间只能有一个创建者
        if (spaceUserEnum == null || SpaceUserEnum.CREATOR.getValue().equals(spaceUserEnum.getValue())) {
            throw new BusinessException(ErrorEnum.PARAM_CHECK_MISTAKE, "角色类型选择错误");
        }
        // 判断用户是否存在
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        if (user == null) {
            throw new BusinessException(ErrorEnum.RESOURCE_NOT_FIND, "用户不存在");
        }
        // 判断空间是否存在
        boolean spaceExist = lambdaQuery().eq(Space::getId, spaceId).exists();
        if (!spaceExist) {
            throw new BusinessException(ErrorEnum.RESOURCE_NOT_FIND, "空间不存在");
        }
        Long userId = user.getId();
        // 先判断用户是否在指定空间
        boolean spaceUserExist = spaceUserService.SpaceUserExist(spaceId, userId);
        if (spaceUserExist) {
            throw new BusinessException(ErrorEnum.REQUEST_MANY, "当前用户已在当前空间");
        }

        SpaceUser spaceUser = new SpaceUser();
        spaceUser.setUserId(userId);
        spaceUser.setSpaceId(spaceId);
        spaceUser.setSpaceRole(spaceUserEnum.getValue());
        return spaceUserService.save(spaceUser);
    }

    @Override
    public SpaceUserVo getSpaceUserAuth(Long id, UserSession userSession) {
        Map<Long, Integer> spaceUserRoleMap = userSession.getSpaceUserRoleMap();
        Integer spaceUserRoleType = spaceUserRoleMap.get(id);
        SpaceUserRole spaceUserRole = spaceUserAuthManager.getSpaceUserRole(spaceUserRoleType);
        List<String> permissions = spaceUserRole.getPermissions();
        SpaceUserVo spaceUserVo = new SpaceUserVo();
        spaceUserVo.setAvatar(userSession.getAvatar());
        spaceUserVo.setSpaceUserRole(spaceUserRole.getRole());
        spaceUserVo.setUserId(userSession.getId());
        spaceUserVo.setPermissions(permissions);
        return spaceUserVo;
    }

    @Override
    public SpaceVo searchSpaceVo(Long id) {
        Space space = getById(id);
        if (space == null) {
            throw new BusinessException(ErrorEnum.RESOURCE_NOT_FIND, "空间不存在");
        }
        SpaceVo spaceVo = SpaceVo.convert(space);

        List<String> spaceUserAvatarList = spaceUserService.getSpaceUserAvatar(id, 5);
        spaceVo.setSpaceUserAvatars(spaceUserAvatarList);
        return spaceVo;
    }

    @Override
    public List<SpaceUserVo> getSpaceUsers(Long id) {
        boolean exists = lambdaQuery().eq(Space::getId, id).exists();
        if (!exists) {
            throw new BusinessException(ErrorEnum.RESOURCE_NOT_FIND, "空间不存在");
        }
        List<SpaceUserVo> spaceUserList = spaceUserService.getSpaceUserList(id);
        for (SpaceUserVo spaceUserVo : spaceUserList) {
            SpaceUserRole spaceUserRole = spaceUserAuthManager.getSpaceUserRole(spaceUserVo.getSpaceRole());
            String userRoleRole = spaceUserRole.getRole();
            spaceUserVo.setSpaceUserRole(userRoleRole);
        }

        return spaceUserList;
    }

    @Override
    public DashboardSpaceRatioVo getSpaceLevelRatio() {
        return this.getBaseMapper().getSpaceLevelRatio();
    }

    /**
     * 校验用户是否有权限创建新空间
     * 指定空间级别 （count<limit）
     *
     * @param userId
     * @return
     */
    private boolean checkUserSpaceAuth(Long userId, SpaceLevelEnum spaceLevelEnum) {
        User user = userMapper.selectById(userId);

        if (user == null) {
            return false;
        }

        if (spaceLevelEnum.getValue() == SpaceLevelEnum.COMMON.getValue()) {
            Integer commonSpaceCount = user.getCommonSpaceCount();
            Integer commonSpaceLimit = user.getCommonSpaceLimit();
            return commonSpaceCount < commonSpaceLimit;
        }

        if (spaceLevelEnum.getValue() == SpaceLevelEnum.FLAGSHIP.getValue()) {
            Integer flagshipSpaceCount = user.getFlagshipSpaceCount();
            Integer flagshipSpaceLimit = user.getFlagshipSpaceLimit();
            return flagshipSpaceCount < flagshipSpaceLimit;
        }

        if (spaceLevelEnum.getValue() == SpaceLevelEnum.PROFESSIONAL.getValue()) {
            Integer proSpaceCount = user.getProSpaceCount();
            Integer proSpaceLimit = user.getProSpaceLimit();
            return proSpaceCount < proSpaceLimit;
        }

        return false;
    }
}




